﻿using System;
using System.Collections.Generic;
using System.Net;
using Honeycomb.Core;
using Honeycomb.Protocol.Messages;
using Honeycomb.Transport;

namespace Honeycomb.Protocol
{
    /// <summary>
    /// Protocol client is responsible for the protocol implementation on the server.
    /// </summary>
    public class ProtocolPeer : ProtocolBase
    {
        /// <summary>
        /// Map of types to MessageTypes.
        /// </summary>
        private static readonly Dictionary<Type, MessageType> typeToMessageTypeMap = new Dictionary<Type, MessageType>
        {
            {typeof (TaskRequest), MessageType.TaskRequest},
            {typeof (AssemblyRequest), MessageType.AssemblyRequest},
            {typeof (ResultRequest), MessageType.ResultRequest},
        };

        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="networkPeer">INetworkPeer implementation.</param>
        public ProtocolPeer(INetworkPeer networkPeer) : base (networkPeer)
        {      
        }

        /// <summary>
        /// Read authenticate request.
        /// </summary>
        /// <returns>Authentication information.</returns>
        public NetworkCredential ReadAuthenticateRequest()
        {
            AuthenticateRequest authenticateRequest = Read<AuthenticateRequest>();
            return new NetworkCredential(authenticateRequest.Username, authenticateRequest.Password);
        }

        /// <summary>
        /// Send authenticate response.
        /// </summary>
        /// <param name="authenticated">If the authentication succeeded or not.</param>
        public void SendAuthenticateResponse(bool authenticated)
        {
            Send(new AuthenticateResponse { Authenticated = authenticated });
        }

        /// <summary>
        /// Read authenticated client request.
        /// </summary>
        /// <returns>Client request information.</returns>
        public ClientRequest ReadAuthenticatedClientRequest()
        {
            // Read message.
            object message = Read(typeof (TaskRequest), typeof (AssemblyRequest), typeof (ResultRequest));           

            // Build client request type.
            ClientRequest request = new ClientRequest();
            request.MessageType = typeToMessageTypeMap[message.GetType()];

            if (request.MessageType == MessageType.AssemblyRequest)
                request.Data = ((AssemblyRequest)message).AssemblyName;

            return request;
        }

        /// <summary>
        /// Send task response.
        /// </summary>
        /// <param name="task">Task to send.</param>
        public void SendTaskResponse(TaskBase task)
        {
            Send(new TaskResponse { SerializedTask = task.Serialize() });
        }

        /// <summary>
        /// Send assembly response.
        /// </summary>
        /// <param name="serializedAssembly">Serialized assembly.</param>
        public void SendAssemblyResponse(byte[] serializedAssembly)
        {
            Send(new AssemblyResponse { Assembly = serializedAssembly });
        }

        /// <summary>
        /// Send result response.
        /// </summary>
        public void SendResultResponse()
        {
            Send(new ResultResponse());
        }
    }
}